﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web;

namespace Web.Ajax.Data
{
	public static class DataContextStorage<T> where T : class
	{
		private static readonly object Threadlock = new object();
		private static string HttpContextKey
		{
			get
			{
				return "" + typeof(T).AssemblyQualifiedName;
			}
		}

		[ThreadStatic]
		private static Stack<T> stack;	//use this if no httpcontext

		public static Stack<T> GetStack()
		{
			if (HttpContext.Current != null)
			{
				var s = (Stack<T>)HttpContext.Current.Items[HttpContextKey];
				if (s == null)
				{
					s = new Stack<T>();
					HttpContext.Current.Items[HttpContextKey] = s;
				}
				return s;
			}
			else
			{
				if (stack == null)
					stack = new Stack<T>();
				return stack;
			}
		}


		public static T Get()
		{
			lock (Threadlock)
			{
				var s = GetStack();
				if (s != null && s.Count > 0)
					return s.Peek();
				return null;
			}
		}

		public static void Push(T obj)
		{
			lock (Threadlock)
			{
				if (obj == null)
					throw new Exception("Failed to create " + typeof(T).Name + " context. " + typeof(T).Name + " passed is null.");
				var s = GetStack();
				s.Push(obj);
			}
		}

		public static void Pop()
		{
			lock (Threadlock)
			{
				var s = GetStack();
				if (s != null && s.Count > 0)
					s.Pop();
			}
		}
	}

	public class DataContext<T> : IDisposable where T : class
	{
		public DataContext(T obj)
		{
			DataContextStorage<T>.Push(obj);
		}

		public static T Get()
		{
			return DataContextStorage<T>.Get();
		}

		public void Dispose()
		{
			DataContextStorage<T>.Pop();
		}
	}
}
